package design_pattern;

// CommunicationDemo.java 描述：生产者和消费者之间的消息传递过程

class ShareData {
  private char c;
  private boolean isProduced = false; // 信号量

  public synchronized void putShareChar(char c) // 同步方法putShareChar()
  {

    if (isProduced) // 如果产品还未消费，则生产者等待
    {
      try {
        wait(); // 生产者等待
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }

    this.c = c;
    isProduced = true; // 标记已经生产
    notify(); // 通知消费者已经生产，可以消费
  }

  public synchronized char getShareChar() // 同步方法getShareChar()
  {
    if (!isProduced) // 如果产品还未生产，则消费者等待
    {
      try {
        wait(); // 消费者等待
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
    isProduced = false; // 标记已经消费
    notify(); // 通知需要生产
    return this.c;
  }

}


class Producer extends Thread // 生产者线程
{
  private ShareData s;

  Producer(ShareData s) {
    this.s = s;
  }

  @Override
  public void run() {

    for (char ch = 'A'; ch <= 'D'; ch++) {
      try {
        Thread.sleep((int) (Math.random() * 3000));
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      s.putShareChar(ch); // 将产品放入仓库
      System.out.println(ch + " is produced by Producer.");
    }
  }
}


class Consumer extends Thread // 消费者线程
{
  private ShareData s;

  Consumer(ShareData s) {
    this.s = s;
  }

  @Override
  public void run() {
    char ch;
    do {
      try {
        Thread.sleep((int) (Math.random() * 3000));
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      ch = s.getShareChar(); // 从仓库中取出产品
      System.out.println(ch + " is consumed by Consumer. ");
    } while (ch != 'D');
  }
}


class CommunicationDemo {
  public static void main(String[] args) {
    ShareData s = new ShareData();
    new Consumer(s).start();
    new Producer(s).start();
  }
}
